package com.yuyou.hxyy.service.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.yuyou.hxyy.service.api.bean.Pagination;
import com.yuyou.hxyy.service.api.entity.DataImport;
import com.yuyou.hxyy.service.api.entity.WordRepo;
import com.yuyou.hxyy.service.api.enums.CategoryEnum;
import com.yuyou.hxyy.service.api.enums.CommEnums;
import com.yuyou.hxyy.service.api.exception.BusinessException;
import com.yuyou.hxyy.service.api.mapper.*;
import com.yuyou.hxyy.service.api.service.IUserWordRepoService;
import com.yuyou.hxyy.service.api.service.IWordRepoService;
import com.yuyou.hxyy.service.api.util.BeanUtils;
import com.yuyou.hxyy.service.api.util.DateUtil;
import com.yuyou.hxyy.service.api.util.DefindBeanUtils;
import com.yuyou.hxyy.service.api.util.Sequence;
import com.yuyou.hxyy.service.api.vo.req.WordRepoExcel;
import com.yuyou.hxyy.service.api.vo.resp.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class WordRepoServiceImpl implements IWordRepoService {

    @Autowired
    private WordRepoMapper mapper;

    @Autowired
    private WordUnitMapper wordUnitMapper;

    @Autowired
    private WordMapper wordMapper;

    @Autowired
    private DataImportMapper dataImportMapper;

    @Autowired
    private UserWordRepoMapper userWordRepoMapper;

    @Autowired
    private UserWordUnitMapper userWordUnitMapper;

    @Autowired
    private IUserWordRepoService userWordRepoService;

    @Override
    public int deleteByPrimaryKey(Long wordRepoId) {
        return mapper.deleteByPrimaryKey(wordRepoId);
    }

    @Override
    public int insert(WordRepo record) {
        return mapper.insert(record);
    }

    @Override
    @Transactional
    public void insertWordRepo(String name, Integer category , Long userId , Integer sort) {
        WordRepo wr = new WordRepo();
        if(sort == null){
            sort = mapper.getMaxSort(category);//获取最大序号
            sort = sort == null ? 1:sort+1;
        }
        wr.setWordRepoId(Sequence.getSequence().nextId());
        wr.setIsDel(0);
        wr.setIsLeaf(0);
        wr.setName(name);
        wr.setCategory(category);
        wr.setCreateTime(new Date());
        wr.setCreateUser(userId);
        wr.setLevel(1);
        wr.setSort(sort);
        insert(wr);

    }

    @Override
    public WordRepo selectByPrimaryKey(Long wordRepoId) {
        return mapper.selectByPrimaryKey(wordRepoId);
    }

    @Override
    public int updateByPrimaryKeySelective(WordRepo record) {


        return mapper.updateByPrimaryKeySelective(record);
    }

    @Override
    @Transactional
    public void updateWordRepo(String name, Long id, Long userId , Integer sort) {
        WordRepo old = selectByPrimaryKey(id);
        if(old == null){ return;}
        WordRepo other = findByNameCategory(name , old.getCategory());
        if(other != null && !other.getWordRepoId().equals(old.getWordRepoId())){//该类别已存在相同名称的词典
            throw new BusinessException("该类别已存在相同名称的词典");
        }
        WordRepo wr = new WordRepo();
        wr.setWordRepoId(id);
        wr.setName(name);
        wr.setUpdateTime(new Date());
        wr.setUpdateUser(userId);
        if(sort != null){
            wr.setSort(sort);
        }
        updateByPrimaryKeySelective(wr);
    }

    @Override
    public int findWordRepoCount(Pagination<WordRepoVo> queryPgn) {
        return mapper.findWordRepoCount(queryPgn);
    }

    @Override
    public List<WordRepoVo> findWordRepoPage(Pagination<WordRepoVo> queryPgn) {
        List<WordRepoVo> list = mapper.findWordRepoPage(queryPgn);
        for (WordRepoVo w :
                list) {
            if(w.getCategory() != null){
                switch (w.getCategory()){
                    case 0:
                            w.setCategaryName(CategoryEnum.Category.PRIMARY_SCHOOL.getName());
                            break;
                    case 1:
                            w.setCategaryName(CategoryEnum.Category.MIDDLE_SCHOOL.getName());
                            break;
                    case 2:
                            w.setCategaryName(CategoryEnum.Category.HIGH_SCHOOL.getName());
                            break;
                    default:
                            w.setCategaryName("");
                }
            }
        }
        return list;
    }

    @Override
    public List<WordRepoVo> findAllWordRepo(Map<String, Object> condition) {
        return mapper.findAllWordRepo(condition);
    }

    @Override
    @Transactional
    public void deleteByIds(String ids) {

        mapper.deleteByIds(ids);
        wordUnitMapper.deleteByRepoIds(ids);//删除所有关卡
        wordMapper.deleteByRepoIds(ids);//删除所有关联单词
        userWordRepoMapper.deleteByRepoIds(ids);//删除所有关联词典学习记录
        userWordUnitMapper.deleteByRepoIds(ids);//删除所有关联关卡学习记录
    }

    @Override
    public WordRepo findByNameCategory(String name, Integer category) {
        return mapper.findByNameCategory(name,category);
    }

    @Override
    public List<WordRepoMapVo> getWordRepoList(Long userId) {
        List<WordRepoStatisticsVo> list = mapper.getWordRepoList();

        //获取词典学习记录
        List<UserWordRepoVo> learnList = userWordRepoService.findLearningList(userId , null);
        List<WordRepoStatisticsVo> learnedList = new ArrayList<>();
        learnList.forEach(l -> list.forEach(w -> {
            if(w.getId().equals(l.getWordRepoId())){
                w.setLearnStatus(l.getStatus());
                if(w.getLearnStatus() == 1){learnedList.add(w);}//正在学习
            }
        }));



        Map<Integer , List<WordRepoStatisticsVo>> map = BeanUtils.toGroup(list , "category");

        List<WordRepoMapVo> resultList = new ArrayList<>();
        WordRepoMapVo learned = new WordRepoMapVo(0,null,null,learnedList);
        resultList.add(learned);
        WordRepoMapVo primary = new WordRepoMapVo(1,0,CategoryEnum.Category.PRIMARY_SCHOOL.getName(),map.get(0));
        resultList.add(primary);
        WordRepoMapVo middle = new WordRepoMapVo(1,1,CategoryEnum.Category.MIDDLE_SCHOOL.getName(),map.get(1));
        resultList.add(middle);
        WordRepoMapVo high = new WordRepoMapVo(1,2,CategoryEnum.Category.HIGH_SCHOOL.getName(),map.get(2));
        resultList.add(high);

        return resultList;
    }


    @Override
    public UserStatisticsVo getUserStatistics(Long userId) {
        UserStatisticsVo usv = new UserStatisticsVo();

        WordRepo wr = mapper.getLatestRepo(userId);//获取最新学习的词典
        if(wr == null){
            return null;
        }

        usv.setWordRepoName(wr.getName());
        usv.setWordRepoId(wr.getWordRepoId());

        //总关卡数
        Integer unitCount = wordUnitMapper.findWordUnitCountByRepo(wr.getWordRepoId());
        usv.setWordUnitCount(unitCount == null?0:unitCount);

        //已学关卡数
        Integer learnedUnitCount = userWordUnitMapper.getLearnedCountByRepo(wr.getWordRepoId() , userId);
        usv.setLearnedWordUnitCount(learnedUnitCount == null?0:learnedUnitCount);

        //词典总单词数
        Integer wordCount = wordMapper.findWordCountByRepo(wr.getWordRepoId());
        usv.setWordCount(wordCount == null ? 0:wordCount);

        //已学单词数
        Integer learnedWordCount = wordMapper.findLearnedWordCountByRepo(wr.getWordRepoId() , userId);
        usv.setLearnWordCount(learnedWordCount == null ? 0:learnedWordCount);

        return usv;
    }

    @Override
    @Transactional
    public DataImport saveWordRepoImport(List<WordRepoExcel> wordRepoExcelList) {
        int total = wordRepoExcelList.size();
        // 有问题的词库不导入
        List<WordRepoExcel> failWordRepoList = checkWordRepoImport(wordRepoExcelList);
        List<WordRepo> wordRepoList = new ArrayList<>(wordRepoExcelList.size());

        for(WordRepoExcel wordRepoExcel : wordRepoExcelList){
            WordRepo wordRepo = new WordRepo();
            wordRepo.setWordRepoId(Sequence.getSequence().nextId());
            wordRepo.setName(wordRepoExcel.getWordRepo());
            wordRepo.setCategory("小学".equals(wordRepoExcel.getCategory()) ? 0 : ("初中".equals(wordRepoExcel.getCategory()) ? 1 : 2));
            wordRepo.setIsLeaf(CommEnums.isLeaf.yes.getValue());
            wordRepo.setSort(wordRepoExcel.getSort());
            wordRepo.setLevel(1);
            wordRepo.setIsDel(CommEnums.isDel.no.getValue());
            wordRepo.setUpdateTime(DateUtil.now());
            wordRepo.setCreateTime(DateUtil.now());
            wordRepoList.add(wordRepo);
        }

        // 批量插入关卡
        if(!CollectionUtils.isEmpty(wordRepoList)){
            mapper.batchInsertWordRepo(wordRepoList);
        }

        /** 导入成败记录 */
        DataImport dataImport = new DataImport();
        dataImport.setId(Sequence.getSequence().getNextId());
        dataImport.setTotal(total);
        dataImport.setSuccNum(wordRepoList.size());
        dataImport.setFailNum(failWordRepoList.size());
        dataImport.setStatus(failWordRepoList.size() > 0 ? "1" : "0");
        dataImport.setType(CommEnums.resourceType.wordRepo.getValue());
        dataImport.setContent(JSON.toJSONString(failWordRepoList));
        dataImport.setCreateTime(DateUtil.now());
        dataImportMapper.insert(dataImport);

        return dataImport;
    }


    private List<WordRepoExcel> checkWordRepoImport(List<WordRepoExcel> wordRepoExcelList) {
        // 导入失败的关卡
        List<WordRepoExcel> failWordRepoList = new ArrayList<>();
        Iterator<WordRepoExcel> iterator = wordRepoExcelList.iterator();
        Set<String> wordRepoSet = new HashSet<>();
        while (iterator.hasNext()) {
            WordRepoExcel wordRepoExcel = iterator.next();
            WordRepoExcel failWordRepo = new WordRepoExcel();
            DefindBeanUtils.copyProperties(wordRepoExcel, failWordRepo);
            StringBuilder failReason = new StringBuilder();

            if (StringUtils.isEmpty(wordRepoExcel.getWordRepo())) {
                failReason.append(";").append("词库为空");
            } else if (wordRepoExcel.getWordRepo().trim().length() > 100) {
                failReason.append(";").append("词库长度大于100");
            } else if (wordRepoSet.contains(wordRepoExcel.getWordRepo())) {
                failReason.append(";").append("导入文件中该词库已经存在");
            } else if (StringUtils.isEmpty(wordRepoExcel.getCategory())) {
                failReason.append(";").append("类别为空");
            } else if (null == wordRepoExcel.getSort()) {
                failReason.append(";").append("序号不能为空");
            }

            WordRepo wordRepo = findByNameCategory(wordRepoExcel.getWordRepo().trim(),
                    ("小学".equals(wordRepoExcel.getCategory()) ? 0 : ("初中".equals(wordRepoExcel.getCategory()) ? 1 : 2)));

            if (null != wordRepo) {
                failReason.append(";").append("词库已经存在");
            }

            // 不符合的，移除不导入
            if (!StringUtils.isEmpty(failReason.toString())) {
                failWordRepo.setFailedReason(failReason.toString().substring(1, failReason.toString().length()));
                failWordRepoList.add(failWordRepo);
                iterator.remove();
            }
        }
        return failWordRepoList;
    }

    @Override
    public XSSFWorkbook failedInfoOfWordRepoImport(List<WordRepoExcel> wordRepoExcelList){

        XSSFWorkbook excel = new XSSFWorkbook();

        XSSFSheet sheet = excel.createSheet("导入失败信息");

        XSSFRow firstRow = sheet.createRow(0);

        String[] titles = new String[] { "词库","类别","序号","导入失败原因"};

        for (int i = 0; i < titles.length; i++) {
            XSSFCell cell = firstRow.createCell(i);

            // 失败原因设置为红色
            if(i == titles.length -1){
                XSSFCellStyle cellStyle = excel.createCellStyle();
                cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
                cell.setCellStyle(cellStyle);
            }
            cell.setCellValue(titles[i]);
        }

        for (int i = 0; i < wordRepoExcelList.size(); i++ ) {

            WordRepoExcel wordRepoExcel = wordRepoExcelList.get(i);

            XSSFRow row = sheet.createRow(i + 1);

            int c = 0;
            XSSFCell cell = row.createCell(c++);
            cell.setCellValue(wordRepoExcel.getWordRepo());

            cell = row.createCell(c++);
            cell.setCellValue(StringUtils.isEmpty(wordRepoExcel.getCategory()) ? "": wordRepoExcel.getCategory());

            cell = row.createCell(c++);
            cell.setCellValue(null == wordRepoExcel.getSort() ? "" : wordRepoExcel.getSort().toString());


            cell = row.createCell(c++);
            // 失败原因设置为红色
            XSSFCellStyle cellStyle = excel.createCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
            cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
            cell.setCellStyle(cellStyle);
            cell.setCellValue(wordRepoExcel.getFailedReason());
        }
        return excel;
    }

}
